const net = require("net");
const protobuf = require("protobufjs");
const path = require("path");

// 配置项
const TCP_SERVER_HOST = "127.0.0.1"; // TCP 服务器地址
const TCP_SERVER_PORT = 7894; // TCP 服务器端口
const TOTAL_CLIENTS = 10000; // 模拟客户端数量
const HEARTBEAT_INTERVAL = 20000; // 心跳包间隔（毫秒）
const BATCH_SIZE = 100; // 每批启动的客户端数量
const BATCH_DELAY = 1000; // 每批启动的时间间隔（毫秒）

// 定义 .proto 文件路径
const PROTO_HEADER_PATH = path.resolve(__dirname, "./PackHeader.proto");
const PROTO_BODY_PATH = path.resolve(__dirname, "./PackData.proto");

let Header, Body;

// 加载 Protobuf 文件
function loadProtobufFiles() {
    return Promise.all([
        new Promise((resolve, reject) => {
            protobuf.load(PROTO_HEADER_PATH, (err, root) => {
                if (err) {
                    console.error("Failed to load PackHeader.proto:", err);
                    reject(err);
                }
                Header = root.lookupType("PackHeader.Header");
                console.log("Header type loaded successfully");
                resolve();
            });
        }),
        new Promise((resolve, reject) => {
            protobuf.load(PROTO_BODY_PATH, (err, root) => {
                if (err) {
                    console.error("Failed to load PackData.proto:", err);
                    reject(err);
                }
                Body = root.lookupType("PackData.Body");
                console.log("Body type loaded successfully");
                resolve();
            });
        }),
    ]);
}

// 构造完整的 Protobuf 数据包
function createProtobufMessage(messageType, clientId, context = null) {
    if (!Header || !Body) {
        throw new Error("Protobuf definitions are not loaded yet.");
    }

    const header = Header.create({
        appId: 1,
        uid: clientId,
        token: "valid-token",
        bizId: 1,
        messageType: messageType, // 消息类型 (0: 登录, 1: 心跳)
        compression: 0,
        encryption: 0,
    });

    const body = Body.create({
        data: JSON.stringify({
            sender_id: clientId,
            receiver_id: null,
            context: context || "",
        }),
    });

    const headerBytes = Header.encode(header).finish();
    const bodyBytes = Body.encode(body).finish();

    const packetBoundary = 0xABCD;
    const version = 1;

    // 构造完整的二进制数据包
    const binaryMessage = Buffer.alloc(16 + headerBytes.length + bodyBytes.length);
    binaryMessage.writeUInt32BE(packetBoundary, 0);
    binaryMessage.writeUInt32BE(version, 4);
    binaryMessage.writeUInt32BE(headerBytes.length, 8);
    binaryMessage.writeUInt32BE(bodyBytes.length, 12);
    headerBytes.copy(binaryMessage, 16);
    bodyBytes.copy(binaryMessage, 16 + headerBytes.length);

    return binaryMessage;
}

// 启动多个客户端（分批启动）
function startClientsBatch() {
    let connectedClients = 0;
    let heartbeatCount = 0;
    let nextClientId = 1; // 唯一递增 ID

    const launchBatch = () => {
        for (let i = 0; i < BATCH_SIZE && nextClientId <= TOTAL_CLIENTS; i++) {
            const clientId = nextClientId++;
            const client = new net.Socket();

            client.connect(TCP_SERVER_PORT, TCP_SERVER_HOST, () => {
                connectedClients++;
                console.log(`Client ${clientId} connected. Total connected: ${connectedClients}`);

                // 发送 Protobuf 格式的登录消息
                const loginMessage = createProtobufMessage(0, clientId, "login request");
                client.write(loginMessage);
            });

            client.on("data", (data) => {
                console.log(`Client ${clientId} received: ${data}`);

                // 登录成功后开始发送心跳包
                if (data.toString().includes("登录连接成功")) {
                    console.log(`Client ${clientId} login successful. Starting heartbeat.`);

                    // 递归 setTimeout 实现心跳包调度
                    const sendHeartbeat = () => {
                        if (client.destroyed) {
                            console.log(`Client ${clientId} connection destroyed. Stopping heartbeat.`);
                            return;
                        }
                        const heartbeatMessage = createProtobufMessage(1, clientId, "heartbeat");
                        client.write(heartbeatMessage);
                        heartbeatCount++;
                        console.log(`Client ${clientId} sent heartbeat. Total heartbeats sent: ${heartbeatCount}`);
                        setTimeout(sendHeartbeat, HEARTBEAT_INTERVAL);
                    };
                    sendHeartbeat(); // 立即开始心跳
                }
            });

            client.on("error", (err) => {
                console.error(`Client ${clientId} error:`, err.message);
            });

            client.on("close", () => {
                connectedClients--;
                console.log(`Client ${clientId} disconnected. Total connected: ${connectedClients}`);
            });
        }

        // 如果还有未启动的客户端，则调度下一批
        if (nextClientId <= TOTAL_CLIENTS) {
            setTimeout(launchBatch, BATCH_DELAY);
        } else {
            console.log("All clients have been started.");
        }
    };

    // 启动第一批客户端
    launchBatch();
}

// 主程序入口
(async function main() {
    try {
        await loadProtobufFiles(); // 确保 Protobuf 文件加载完成
        startClientsBatch(); // 分批启动客户端
    } catch (err) {
        console.error("Error initializing:", err);
    }
})();
